﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using CommonBehaviors.Actions;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals.WoWObjects;

using Action = Styx.TreeSharp.Action;

namespace PetBuddy.Helpers
{
    public class Fighter
    {
        #region Variables

        private static LocalPlayer Me = PetBuddy.Me;
        public static Fighter Instance = new Fighter();

        public static Stopwatch CombatTimer;
        public static int PetBalleRound;

        public static PetConsts.BattleStates BattleState = 0;

        public static bool IsInCombat;
        private static bool preCombatDataCollected;
        static DateTime _lastFight = DateTime.Now.Subtract(new TimeSpan(10, 0, 0));

        static List<BattlePetFieldInfoStruct> FieldMyPets { get { return UpdateBattlePetsStats(1); } }

        static List<BattlePetFieldInfoStruct> FieldEnemyPets { get { return UpdateBattlePetsStats(2); } }

        #endregion


        #region Structs & Constants

        public struct petAbilities
        {
            public int id;
            public int type;
        }

        public struct BattlePetFieldInfoStruct
        {
            public string petGUID;
            public string Name;
            public int health;
            public int maxHealth;
            public int petType;
            public List<petAbilities> abilityList;
        }

        #endregion


        #region BattleCounters

        public struct BattleResultStruct
        {
            public DateTime when;
            public bool result;
        }

        public static List<BattleResultStruct> WinsLooses = new List<BattleResultStruct>();

        #endregion

        #region Util

        static int BattleResult
        {
            get
            {
                var res = 0;
                if ((PetBattles.GetHealth() + PetBattles.GetHealth(1, 2) + PetBattles.GetHealth(1, 3)) > 0) res++;
                if ((PetBattles.GetHealth(2) + PetBattles.GetHealth(2, 2) + PetBattles.GetHealth(2, 3)) > 0) res--;
                return res;
            }
        }

        static bool GetCurrentPetsForStatistics()
        {
            var _tempStat = PetBuddy.LvLupStatistic;
            for (int i = 1;i <= 3;i++)
            {
                var _l_info = PetJournal.GetPetLoadOutInfo(i);
                if (_l_info.petGUID == null) return false;

                var _p_info = !_l_info.locked ? PetJournal.GetPetInfoByPetGUID(_l_info.petGUID) : new PetJournal._PetInfo {isOwned = false};
                if (!_p_info.isOwned) continue;
                var petIndex = _tempStat.FindIndex(p => p.Name == _p_info.petName);

                if (petIndex >= 0)
                {
                    var newStat = new PetBuddy.PetLvLstatStruct
                                      {
                                          petGUID = _l_info.petGUID,
                                          Name = _p_info.petName,
                                          startLevel = Math.Max(_tempStat[petIndex].startLevel, _p_info.level),
                                          curLevel = _p_info.level
                                      };

                    _tempStat[petIndex] = newStat;

                } else
                {
                    _tempStat.Add(new PetBuddy.PetLvLstatStruct
                                      {
                                          petGUID = _l_info.petGUID,
                                          Name = _p_info.petName,
                                          startLevel = _p_info.level,
                                          curLevel = _p_info.level
                                      });
                }
            }
            PetBuddy.LvLupStatistic = _tempStat;
            return true;
        }
        
        static List<BattlePetFieldInfoStruct> UpdateBattlePetsStats(int side)
        {
            var ret = new List<BattlePetFieldInfoStruct>(3);
            for (var i = 1;i <= 3;i++)
            {
                var pet = new BattlePetFieldInfoStruct
                              {
                                  petGUID = side == 1 && !PetJournal.GetPetLoadOutInfo(i).locked ? PetJournal.GetPetLoadOutInfo(i).petGUID : "",
                                  Name = PetBattles.GetName(side, i),
                                  health = PetBattles.GetHealth(side, i),
                                  maxHealth = PetBattles.GetMaxHealth(side, i),
                                  petType = PetBattles.GetPetType(side, i),
                                  abilityList = new List<petAbilities>()
                              };
                for (var j = 1;j <= 3;j++)
                    pet.abilityList.Add(new petAbilities
                                            {
                                                id = PetBattles.GetAbilityInfo(side, i, j).id,
                                                type = PetBattles.GetAbilityInfo(side, i, j).petType
                                            });
                ret.Add(pet);
            }
            return ret;
        }

        #endregion

        #region Routine

        public static Composite PetCombatBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => !CombatTimer.IsRunning,
                              new Action(ret =>
                                  {
                                      CombatTimer.Reset();
                                      CombatTimer.Start();
                                      Seeker.InteractTimer.Reset();
                                      Seeker.InteractTimer.Stop();
                                      return RunStatus.Failure;
                                  })),

                new Decorator(ret => CombatTimer.IsRunning,
                              new Sequence(

                                  new Action(ret =>
                                      {
                                          BattleState = PetBattles.IsInBattle ? PetBattles.GetBattleState : PetConsts.BattleStates.NOT_IN_COMBAT;
                                          PetBuddy.dlog("[Fightor] State: " + BattleState.ToString());
                                      }),

                                  new PrioritySelector(

                                      new Decorator(ret => BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_WAITING_FOR_FRONT_PETS |
                                                           BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_WAITING_FOR_ROUND_PLAYBACK |
                                                           BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_WAITING_PRE_BATTLE,
                                                    new Action(ret => IsInCombat = true)
                                          ),

                                      new Decorator(ret => (BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_FINAL_ROUND |
                                                            BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_FINISHED) &
                                                           _lastFight <= DateTime.Now.Subtract(new TimeSpan(0, 0, 3)),
                                                    new Sequence(

                                                        new Action(ret =>
                                                            {
                                                                _lastFight = DateTime.Now;
                                                                preCombatDataCollected = false;
                                                            }),

                                                        new PrioritySelector(

                                                            new Decorator(ret => BattleResult > 0, //we win
                                                                          new Sequence(
                                                                              new Action(ret => WinsLooses.Add(new BattleResultStruct {result = true, when = DateTime.Now})),
                                                                              PetBuddy.aglog("WE WON!")
                                                                              )),

                                                            new Decorator(ret => BattleResult < 0, //we loose
                                                                          new Sequence(
                                                                              new Action(ret => WinsLooses.Add(new BattleResultStruct {result = false, when = DateTime.Now})),
                                                                              PetBuddy.arlog("We Loose.")
                                                                              )),

                                                            new Decorator(ret => BattleResult == 0, //Left battle
                                                                          new Sequence(
                                                                              new Action(ret => WinsLooses.Add(new BattleResultStruct {result = false, when = DateTime.Now})),
                                                                              PetBuddy.aslog("We Flee.")
                                                                              ))
                                                            ),

                                                        new Action(ret => PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE)
                                                        )),

                                      new Decorator(ret => PetBattles.IsInBattle && BattleState == PetConsts.BattleStates.LE_PET_BATTLE_STATE_ROUND_IN_PROGRESS,
                                                    new Sequence(
                                                        new Action(ret => IsInCombat = true),
                                                        new Decorator(ret => !preCombatDataCollected,
                                                                      new Action(ret => preCombatDataCollected = GetCurrentPetsForStatistics())
                                                            )

                                                        //TODO Pet Combat Behavior

                                                        ))
                                      )
                                  ))
                );
        }

        #endregion
    }
}
